package com.hl.stickerlibrary.sticker;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Handler;
import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextWatcher;
import android.text.style.RelativeSizeSpan;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ScrollView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.hl.stickerlibrary.R;

import java.util.List;

public class ExSticker extends FrameLayout {
    private Context context;
    private ScrollView mScrollView;
    private StickerView mStickerView;
    private EditText mEtContent;
    private FrameLayout mFlSticker;
    private int scrollHeight;
    private String typefacePath;
    private String typefaceUrl;
    private String typefaceId;
    private SpannableString span;
    private Handler handler = new Handler();

    public ExSticker(Context context) {
        this(context, null);
    }

    public ExSticker(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ExSticker(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @SuppressLint("ClickableViewAccessibility")
    public void init(Context context) {
        this.context = context;
        LayoutInflater.from(context).inflate(R.layout.view_exsticker, this, true);
        mScrollView = findViewById(R.id.scrollView);
        mStickerView = findViewById(R.id.sticker_view);
        mEtContent = findViewById(R.id.et_content);
        mFlSticker = findViewById(R.id.fl_sticker);

        ViewTreeObserver vto = mScrollView.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mScrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                scrollHeight = mScrollView.getMeasuredHeight();
                mStickerView.setMinHeight(scrollHeight);
                calculateHeight();
            }
        });

        mStickerView.setBackgroundColor(Color.TRANSPARENT);
        mStickerView.setLocked(false);
        mStickerView.setConstrained(false);

        mStickerView.setOnStickerOperationListener(new StickerView.OnStickerOperationListener() {
            @Override
            public void onStickerAdded(@NonNull Sticker sticker) {
                postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        hideSoftInput();
                        calculateHeight();
                    }
                }, 100);
            }

            @Override
            public void onStickerClicked(@NonNull Sticker sticker) {
                if (stickersClickListener != null) {
                    stickersClickListener.onClick(sticker);
                }
                hideSoftInput();
            }

            @Override
            public void onStickerDeleted(@NonNull Sticker sticker) {
                hideSoftInput();
                calculateHeight();
            }

            @Override
            public void onStickerDragFinished(@NonNull Sticker sticker) {
                hideSoftInput();
                calculateHeight();
            }

            @Override
            public void onStickerTouchedDown(@NonNull Sticker sticker) {
                hideSoftInput();
            }

            @Override
            public void onStickerZoomFinished(@NonNull Sticker sticker) {
                hideSoftInput();
                calculateHeight();
            }

            @Override
            public void onStickerFlipped(@NonNull Sticker sticker) {
                hideSoftInput();
            }

            @Override
            public void onRotate(float angle) {
                System.out.println("onRotate:    " + angle);
            }

            @Override
            public void onStickerDoubleTapped(@NonNull Sticker sticker) {
                hideSoftInput();
            }

            @Override
            public void onStickerOutAreaClick() {
                if (stickersClickListener != null) {
                    stickersClickListener.onClick(null);
                }
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        hideSoftInput();
                    }
                }, 100);
            }
        });

        mEtContent.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        calculateHeight();
                    }
                }, 100);
            }
        });


        mEtContent.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                //获取到焦点显示光标
                handler.removeCallbacksAndMessages(null);
                mEtContent.setCursorVisible(true);
                return false;
            }
        });
    }

    private void hideSoftInput() {
        mEtContent.setCursorVisible(false);
        InputMethodManager im = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        im.hideSoftInputFromWindow(mEtContent.getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }

    public void calculateHeight() {
        int etContentHeight = mEtContent.getHeight();
        int cY = mStickerView.getCurrentHeight();
        cY = Math.max(etContentHeight, cY) + mStickerView.getPaddingBottom();
        ViewGroup.LayoutParams params = mStickerView.getLayoutParams();
        if (params != null) {
            if (cY != scrollHeight && cY >= mStickerView.getMinHeight()) {
                params.height = cY;
            } else if (cY < mStickerView.getMinHeight() || params.height < mStickerView.getMinHeight()) {
                params.height = mStickerView.getMinHeight();
            } else {
                return;
            }
            mStickerView.setLayoutParams(params);
        }
    }

    public StickerView getStickerView() {
        return mStickerView;
    }

    public FrameLayout getFlSticker() {
        return mFlSticker;
    }

    public void setFontSize(int size) {
        int start = mEtContent.getSelectionStart();
        int end = mEtContent.getSelectionEnd();
        if (start != end) {
            try {
                span = new SpannableString(mEtContent.getText().toString());
                float text_size = (float) (size - 12) / 24 + 1;
                span.setSpan(new RelativeSizeSpan(text_size), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                mEtContent.setText(span);

                mEtContent.setSelection(start, end);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            mEtContent.setTextSize(size);
        }
        calculateHeight();
    }

    public void setTypeface(Typeface ttf) {
        mEtContent.setTypeface(ttf);
        calculateHeight();
    }

    public void setNoTypeface() {
        mEtContent.setTypeface(null);
        calculateHeight();
    }

    public void setFontItalic(boolean italic) {
        mEtContent.getPaint().setTextSkewX(italic ? -0.5f : 0f);
        mEtContent.setText(mEtContent.getText());
        mEtContent.setSelection(mEtContent.getText().length());
        calculateHeight();
    }

    public void setFontUnderline(boolean underline) {
        mEtContent.getPaint().setUnderlineText(underline);
        mEtContent.setText(mEtContent.getText());
        mEtContent.setSelection(mEtContent.getText().length());
        calculateHeight();
    }

    public void setFontBold(boolean bold) {
        mEtContent.getPaint().setFakeBoldText(bold);
        mEtContent.setText(mEtContent.getText());
        mEtContent.setSelection(mEtContent.getText().length());
        calculateHeight();
    }

    public void setFontGravity(int gravity) {
        mEtContent.setGravity(gravity);
        calculateHeight();
    }

    public String getEditContent() {
        return mEtContent.getText().toString();
    }

    public void setEditContent(String content) {
        mEtContent.setText(content);
        calculateHeight();
    }

    @NonNull
    public StickerView setLocked(boolean locked) {
        return mStickerView.setLocked(locked);
    }

    public void moveUpSticker() {
        Sticker sticker = mStickerView.getCurrentSticker();
        if (sticker != null) {
            List<Sticker> list = mStickerView.getStickers();
            int index = list.indexOf(sticker);
            if (index != list.size() - 1) {
                list.remove(sticker);
                list.add(index + 1, sticker);
                mStickerView.invalidate();
            }
        }
    }

    /**
     * 是否可以移到上一层
     *
     * @return
     */
    public boolean canMoveUp() {
        Sticker sticker = mStickerView.getCurrentSticker();
        if (sticker != null) {
            List<Sticker> list = mStickerView.getStickers();
            int index = list.indexOf(sticker);
            if (index < list.size() - 1) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否可以移到下一层
     *
     * @return
     */
    public boolean canMoveDown() {
        Sticker sticker = mStickerView.getCurrentSticker();
        if (sticker != null) {
            List<Sticker> list = mStickerView.getStickers();
            int index = list.indexOf(sticker);
            if (index > 0) {
                return true;
            }
        }
        return false;
    }

    public void moveDownSticker() {
        Sticker sticker = mStickerView.getCurrentSticker();
        if (sticker != null) {
            List<Sticker> list = mStickerView.getStickers();
            int index = list.indexOf(sticker);
            if (index != 0) {
                list.remove(sticker);
                list.add(index - 1, sticker);
                mStickerView.invalidate();
            }
        }
    }

    public List<Sticker> getStickers() {
        return mStickerView.getStickers();
    }

    public Sticker getCurrentSticker() {
        return mStickerView.getCurrentSticker();
    }

    public void setCursorVisible(boolean show) {
        if (show) {
            postDelayed(new Runnable() {
                @Override
                public void run() {
                    mEtContent.setCursorVisible(true);
                }
            }, 100);
        } else {
            mEtContent.setCursorVisible(show);
        }
    }

    public void update() {
        mStickerView.invalidate();
    }

    public EditText getEdittext() {
        return mEtContent;
    }

    public void refresh() {
        mStickerView.invalidate();
    }

    public String getTypefacePath() {
        return typefacePath;
    }

    public void setTypefacePath(String typefacePath) {
        this.typefacePath = typefacePath;
    }

    public String getTypefaceUrl() {
        return typefaceUrl;
    }

    public void setTypefaceUrl(String typefaceUrl) {
        this.typefaceUrl = typefaceUrl;
    }

    public String getTypefaceId() {
        return typefaceId;
    }

    public void setTypefaceId(String typefaceId) {
        this.typefaceId = typefaceId;
    }

    public Object[] getSpans() {
        final Editable editable = mEtContent.getEditableText();
        Object[] atSpans = editable.getSpans(0, mEtContent.getText().length(), Object.class);
        return atSpans;
    }

    public void setSpan(SpannableString span) {
        this.span = span;
    }

    public void addSticker(@NonNull Sticker sticker) {
        mStickerView.addSticker(sticker);
    }

    public void addSticker(@NonNull final Sticker sticker, final @Sticker.Position int position) {
        mStickerView.addSticker(sticker, position);
    }

    private OnStickersClickListener stickersClickListener;

    public void setStickersClickListener(OnStickersClickListener stickersClickListener) {
        this.stickersClickListener = stickersClickListener;
    }

    public interface OnStickersClickListener {
        void onClick(Sticker sticker);
    }
}